package com.luo.d3s.light.mybatis.ec.application.service.impl;

import com.luo.d3s.core.application.dto.Response;
import com.luo.d3s.core.application.dto.SingleResponse;
import com.luo.d3s.core.util.validation.Validates;
import com.luo.d3s.ext.event.jdbc.EventBus;
import com.luo.d3s.light.mybatis.ec.application.assembler.OrderAssembler;
import com.luo.d3s.light.mybatis.ec.application.dto.command.OrderCreateCommand;
import com.luo.d3s.light.mybatis.ec.application.dto.command.OrderDeliverCommand;
import com.luo.d3s.light.mybatis.ec.application.dto.event.OrderPaidEvent;
import com.luo.d3s.light.mybatis.ec.application.service.OrderCommandService;
import com.luo.d3s.light.mybatis.ec.domain.order.Order;
import com.luo.d3s.light.mybatis.ec.domain.order.OrderRepository;
import com.luo.d3s.light.mybatis.ec.domain.order.acl.PaymentAcl;
import com.luo.d3s.light.mybatis.ec.domain.order.acl.StockAcl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 订单命令处理服务实现类
 *
 * @author luohq
 * @date 2022-11-27 19:16
 */
@Service
public class OrderCommandServiceImpl implements OrderCommandService {

    private OrderRepository orderRepository;

    private PaymentAcl paymentAcl;

    private StockAcl stockAcl;

    public OrderCommandServiceImpl(OrderRepository orderRepository, PaymentAcl paymentAcl, StockAcl stockAcl) {
        this.orderRepository = orderRepository;
        this.paymentAcl = paymentAcl;
        this.stockAcl = stockAcl;
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public SingleResponse<Long> createOrder(OrderCreateCommand orderCreateCommand) {
        // 创建订单（领域对象创建动作，底层调用OrderFactory进行创建）
        // 注：正常此处需直接调用OrderFactory进行创建，但出于考虑代码整洁度，故将此段OrderFactory.create逻辑统一移到OrderAssembler中
        Order order = OrderAssembler.createOrder(orderCreateCommand);
        // 锁库存
        this.stockAcl.lockStock(order);
        // 持久化订单
        order = this.orderRepository.save(order);
        return SingleResponse.of(order.getId());
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Response payOrder(Long orderId) {
        Order order = this.orderRepository.findById(orderId);
        Validates.notNull(order, "order not exist!");
        // 调用第三方支付系统支付订单
        this.paymentAcl.payOrder(order);
        // 支付订单
        order.payOrder();
        this.orderRepository.save(order);
        // 发送订单已支付事件
        EventBus.publish(new OrderPaidEvent(order));
        return Response.buildSuccess();
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Response deliverOrder(OrderDeliverCommand orderDeliverCommand) {
        Order order = this.orderRepository.findById(orderDeliverCommand.getOrderId());
        Validates.notNull(order, "order not exist!");
        // 订单已发货
        order.deliverOrder(orderDeliverCommand.getExpressCode(), orderDeliverCommand.getDeliveryTime());
        this.orderRepository.save(order);
        return Response.buildSuccess();
    }


    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Response completeOrder(Long orderId) {
        Order order = this.orderRepository.findById(orderId);
        Validates.notNull(order, "order not exist!");
        // 完成订单
        order.completeOrder();
        this.orderRepository.save(order);
        return Response.buildSuccess();
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Response cancelOrder(Long orderId) {
        Order order = this.orderRepository.findById(orderId);
        Validates.notNull(order, "order not exist!");
        // 取消订单
        order.cancelOrder();
        this.orderRepository.save(order);
        return Response.buildSuccess();
    }
}
